home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / What's New? / Tool Chest / ATA Demo 1.3 / ATA Demo.c next >
Encoding:
Text File  |  1999-03-15  |  22.9 KB  |  809 lines  |  [TEXT/CWIE]

  1. /*/*************************************************************************
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Macintosh ATA Manager Sample 
  5. **
  6. **    by Vinne Moscaritolo, <vinnie@apple.com>
  7. **    Apple Developer Technical Support 
  8. **
  9. **  Created from as much sample code I could find.
  10. **  with much help from Gary Wilkinson, Rich Schnell,  Martin Minow
  11. **    my man Serge, and Bun-Bun the Rabbit.
  12. **
  13. **  " Good Artists Imitate, Great Artist Steal "
  14. **
  15. **    File:        ATA Demo.c
  16. **
  17. **    Copyright © 1996, 1997, 1998, 1999 Apple Computer, Inc.
  18. **    All rights reserved.
  19. **
  20. **    Modifications:
  21. **
  22. **        990315    Vin        Updated to CW 4 and it's headers.
  23. **                        Added code to set the standard .AppleCD driver
  24. **                        into a quiescent state and thus allow us to
  25. **                        query the ATA bus without disturbing the .AppleCD driver. 
  26. **                        
  27. **        980625    Vin        Buffer was still the incorrect size in 
  28. **                        DisplayATADriveIdentity routine.
  29. **                        Buffer needs to be 256 words (for 512 bytes long). 
  30. **                        Drive identify just assumes you have allocated a
  31. **                        512 byte buffer and writes it accordingly.  In
  32. **                        this case it overwrites the end of the array.
  33. **
  34. **                        Modified to CW Pro 3 and its headers
  35. **
  36. **
  37. **        971005    BLoB    Buffer was incorrect size in 
  38. **                        DisplayATADriveIdentity routine.
  39. **                        Modified to CW Pro 1 and its headers
  40. **                        Added Metrowerks SIOUX specific stuff
  41. **                        Created Fat application
  42. **                        Realized that the words come back swapped; 
  43. **                        adjusted for this in the DumpFormatedBuffer routine.
  44. **
  45. **    You may incorporate this sample code into your applications without
  46. **    restriction, though the sample code has been provided "AS IS" and the
  47. **    responsibility for its operation is 100% yours.  However, what you are
  48. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  49. **    after having made changes. If you're going to re-distribute the source,
  50. **    we require that you make it clear in the source that the code was
  51. **    descended from Apple Sample Code, but that you've made changes.
  52. **
  53. **************************************************************************/
  54.  
  55.  
  56.  
  57. //------------------------------------------------------------------------------------
  58. #pragma mark Includes
  59. //------------------------------------------------------------------------------------
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <LowMem.h>
  63. #include <Patches.h>
  64. #include <Traps.h>
  65. #include <Devices.h>
  66.  
  67. #include <ATA.h>
  68. #ifdef __MWERKS__
  69.     #include <SIOUX.h>
  70. #endif
  71. #include "ata_powerpc.h"
  72. //------------------------------------------------------------------------------------
  73. #pragma mark Defines
  74. //------------------------------------------------------------------------------------
  75.  
  76. //
  77. // Identifies the bus protocol type.
  78. //
  79.  
  80. enum {
  81.     kDevUnknown        =    0,
  82.     kDevATA            =    1,
  83.     kDevATAPI        =    2,
  84.     kDevPCMCIA        =    3
  85. };
  86.  
  87. //
  88. // Identifies the Socket type.
  89. //
  90. enum {
  91.     kSocketUnknown        =    0,
  92.     kSocketInternal        =    1,
  93.     kSocketMediaBay        =    2,
  94.     kkSocketPCMCIA        =    3
  95. };
  96.  
  97.  
  98. // .AppleCD contants 
  99. enum
  100.     {
  101.     csSetPowerMode    =    70,
  102.     csQuiescence    =    0x437
  103.     };
  104.  
  105. enum
  106.     {
  107.     pmActive        =    0,
  108.     pmStandby        =    1,
  109.     pmIdle            =    2,
  110.     pmSleep            =    3
  111.     };
  112.  
  113. enum
  114.     {
  115.     quiescenceON    =    0,
  116.     quiescenceOFF    =    1
  117.     };
  118.  
  119.  
  120. //------------------------------------------------------------------------------------
  121. #pragma mark Macros
  122. //------------------------------------------------------------------------------------
  123.  
  124. #define CLEAR(what) do {                        \
  125.         register Ptr        _ptr = (Ptr) &what;    \
  126.         register Size        _len = sizeof what;    \
  127.         for (; _len > 0; --_len)                    \
  128.             *_ptr++ = 0;                        \
  129.     } while (0)
  130.  
  131. #define IF_ERROR(_err_,_str_) if (_err_ != noErr) { printf(_str_); return (_err_); }
  132.  
  133.  
  134. //------------------------------------------------------------------------------------
  135. #pragma mark -
  136.  
  137. //------------------------------------------------------------------------------------
  138. #pragma mark Identify Drive Info
  139. //------------------------------------------------------------------------------------
  140.  
  141. //
  142. //  Bit fields returned from Identify Drive command
  143. //
  144. enum {
  145.     magdrv_bit        =    15,            /* WORD 0: bit number of mag drive indicator    */
  146.     rcd_bit            =    7,            /* WORD 0: bit number of removable indicator    */
  147.     fixed_bit        =    6,            /* WORD 0: bit number of fixed disk indicator    */
  148.  
  149.     lbamode_bit        =    9,            /* bit number of lba support indicator            */
  150.     iordy_bit        =    11,            /* bit number of IORDY support indicator        */
  151.     extvalid_bit    =    1,            /* bit number of valid extension word            */
  152.     mode3_bit        =    0,            /* WORD 64: bit number of mode 3 support        */
  153.     
  154.     kMagDrv            =    1 << magdrv_bit,    /* Bit 15 = 0 -> a magnetic drive        */
  155.     kRemovable        =    1 << rcd_bit,        /* Bit 7 != 0 -> removable cartridge    */
  156.     kFixed            =    1 << fixed_bit,        /* Bit 6 != 0 -> indicates fixed drive    */
  157.     kLBAMode        =    1 << lbamode_bit,    /* LBA support indicator                */
  158.     kIORDY            =    1 << iordy_bit,        /* IORDY support indicator                */
  159.     kExtValid        =    1 << extvalid_bit,    /* Extension word valid                    */
  160.     MODE3BIT        =    1 << mode3_bit        /* mode 3 bit in word 64 of ident data    */
  161. };
  162.  
  163. //
  164. // This is returned by the device in response to an IDENTIFY command (512 bytes).
  165. //
  166. typedef    struct IdentifyBlock {    /* Structure of Identify data                        */
  167.     short    Signature;            /* Word 00: Constant value                            */
  168.     short    NumCyls;            /* Word 01:    Number of cylinders (default mode)            */
  169.     short    RSVD0;                /* Word 02:    Constant value of 0                        */
  170.     short    NumHds;                /* Word 03:    Number of heads (default mode)            */
  171.     short    TrkBytes;            /* Word 04:    Number of unformatted bytes/track        */
  172.     short    SecBytes;            /* Word 05:    Number of unformatted bytes/sector        */
  173.     short    NumSecs;            /* Word 06:    Number of sectors/track                    */
  174.     short    VU0;                /* Word 07:    Vendor unique                            */
  175.     short    VU1;                /* Word 08:    Vendor unique                            */
  176.     short    VU2;                /* Word 09:    Vendor unique                            */
  177.     short    Serial[10];            /* Word 10-19:    Serial Number (right-justified)        */
  178.     short    BufType;            /* Word 20:    Buffer Type                                */
  179.     short    BufSize;            /* Word 21:    Buffer size in 512 byte increments        */
  180.     short    NumECC;                /* Word 22:    Number of ECC bytes                        */
  181.     short    FirmRev[4];            /* Word 23-26:    Firmware revision (left-justified)    */
  182.     short    ModelNum[20];        /* Word 27-46:    Model number (left-justified)        */
  183.     short    MultCmds;            /* Word 47:    R/W multiple commands not impl = 0        */
  184.     short    DblXferFlag;        /* Word 48:    Double transfer flag                    */
  185.     short    Capabilities;        /* Word 49: LBA, DMA, IORDY support indicator        */
  186.     short    Reserved1;            /* Word 50: Reserved                                */
  187.     short    PIOTiming;            /* Word 51: PIO transfer timing mode                */
  188.     short    DMATiming;            /* Word 52:    DMA transfer timing mode                */
  189.     short    Extension;            /* Word 53: extended info support                    */
  190.     short    CurCylinders;        /* Word 54: number of current cylinders                */
  191.     short    CurHeads;            /* Word 55: number of current heads                    */
  192.     short    CurSPT;                /* Word 56: number of current sectors per track        */
  193.     short    CurCapacity[2];        /* Word 57-58: current capacity in sectors            */
  194.     short    MultSectors;        /* Word 59: Multiple sector setting                    */
  195.     short    LBACapacity[2];        /* Word 60-61: total sectors in LBA mode            */
  196.     short    SWDMA;                /* Word 62: single word DMA support                    */
  197.     short    MWDMA;                /* Word 63: multi word DMA support                    */
  198.     short    APIOModes;            /* Word 64:    Advanced PIO Xfr mode supported            */
  199.     short    MDMATiming;            /* Word 65:    Minimum Multiword DMA Xfr Cycle            */
  200.     short    RDMATiming;            /* Word 66:    Recommended Multiword DMA Cycle            */
  201.     short    MPIOTiming;            /* Word 67:    Min PIO XFR Time W/O Flow Control        */
  202.     short    PIOwRDYTiming;        /* Word 68:    Min PIO XFR Time with IORDY flow ctrl    */
  203.     short    Reserved[187];        /* Word 69-255: Reserved                            */
  204. } IdentifyBlock;
  205.  
  206. //
  207. // The following structure and table simplifies the formatting.
  208. //
  209. enum {
  210.     kEndOfTable = 0,            /* Marker                                            */
  211.     kDecimal,                    /* Signed integer (two words are high..low)            */
  212.     kHex,                        /* Bitfield                                            */
  213.     kLeftJust,                    /* Ascii, left-justified, space padded                */
  214.     kRightJust                    /* Ascii, right-justified, space padded                */
  215. };
  216. struct FormatTable {
  217.     short        firstWord;        /* First word in IdentifyBlock cast to short vector    */
  218.     short        lastWord;        /* Last word in IdentifyBlock cast to short vector    */
  219.     short        format;            /* Format from above enum                            */
  220.     const char    *label;            /* Text to display                                    */
  221. };
  222.  
  223. typedef struct FormatTable FormatTable, *FormatTablePtr;
  224.  
  225. FormatTable kIdentFormat[] = {
  226.     {     0,     0, kHex,        "Configuration word"                        },
  227.     {     1,     1,    kDecimal,    "Cylinders"            },
  228.     {     3,     3,    kDecimal,    "Heads"                },
  229.     {     4,     4,    kDecimal,    "Bytes/Track"            },
  230.     {     5,     5,    kDecimal,    "Bytes/Sector (0 = 512 bytes)"        },
  231.     {     5,     5,    kDecimal,    "Sectors/Track"        },    /* 35 */
  232.     {     7,     9,    kHex,        "Vendor Unique (word 7..9)"                    },
  233.     {    10,    19,    kRightJust,    "Serial Number"                                },
  234.     {    20,    20,    kHex,        "Buffer Type"                                },
  235.     {    21,    21,    kDecimal,    "Buffer size in 512 byte increments"        },
  236.     {    22,    22,    kDecimal,    "Number of ECC bytes available"                },
  237.     {    23,    26,    kLeftJust,    "Firmware Revision"                            },
  238.     {    27,    46,    kLeftJust,    "Model Number"                                },
  239.     {    47,    53,    kHex,        "Capability Flags (word 47..53)"            },
  240.     {    54,    54,    kDecimal,    "Cylinders (current mode)"        },
  241.     {    55,    55,    kDecimal,    "Heads (current mode)"            },
  242.     {    56,    56,    kDecimal,    "Sectors/Track (current mode)"        },
  243.     {    57,    58,    kDecimal,    "Current Capacity in Sectors"                },
  244.     {    59,    59,    kHex,        "Multiple Sector Capability Flag"            },
  245.     {    60,    61,    kDecimal,    "Current User-addressable Sectors"            },
  246.     {    62,    62,    kHex,        "Single Word DMA Transfer Mode Flags"        },
  247.     {    63,    63,    kHex,        "Multiword DMT Transfer Mode Flags"            },
  248.     {     0,  0,    kEndOfTable,""                                            }
  249. };
  250.  
  251.  
  252.  
  253. //------------------------------------------------------------------------------------
  254. #pragma mark Prototypes
  255. //------------------------------------------------------------------------------------
  256.  
  257. Boolean     ATAManagerPresent    (void);
  258. Boolean     ATAHardwarePresent    (void);
  259. Boolean     TrapAvailable        (short theTrap);
  260. void         PrintNumVersion        (char *label, NumVersion version );
  261. OSErr         DisplayATAManagerInquiryInfo (void);
  262.  
  263. OSErr         ScanATABusses         (void);
  264. OSErr         DisplayATADriveIdentity (UInt32 deviceID );
  265. void        DumpRawBuffer        ( UInt8 *bufferPtr, int length );
  266. void        DumpFormatedBuffer    (void* p, const  FormatTablePtr formatPtr);
  267. char*        DrvrRefToName        (short refNum);
  268.  
  269. OSErr         DisableCDDriver     (SInt16 refNum);
  270. OSErr         EnableCDDriver         (SInt16 refNum);
  271. OSErr         WakeUpCDDrive         (SInt16 refNum);
  272. OSErr         SetQuiescence         (SInt16 refNum, UInt16 mode);
  273.  
  274.  
  275. //------------------------------------------------------------------------------------
  276. #pragma mark -
  277.  
  278.  
  279. // ---------------------------------------------------------------------------
  280. void     main     (void)
  281. // ---------------------------------------------------------------------------
  282. {
  283.     OSErr            status;
  284.     SInt16            drvrRefNum  = 0;
  285.     
  286. #ifdef __MWERKS__
  287.     SIOUXSettings.asktosaveonclose = false;
  288. #endif
  289.  
  290.     printf("Macintosh ATA Manager Sample\n\n");
  291.  
  292. // Check for ATA Hardware 
  293. // you should do this before calling the ATAManager, since some early ROMS
  294. // could indicate an ATA manager without the proper HW, thus casing a crash.
  295.     if (ATAHardwarePresent() == false) {
  296.         printf("ATA Hardware is not present on this system\n");
  297.         exit(EXIT_FAILURE);
  298.     }
  299.  
  300. // Check for ATA Manager
  301.     if (ATAManagerPresent() == false) {
  302.         printf("ATA Manager is not present on this system\n");
  303.         exit(EXIT_FAILURE);
  304.     }
  305.         
  306. // Display ATA Manager Info
  307.     status = DisplayATAManagerInquiryInfo();
  308.     if (status != noErr) {
  309.         printf("Cannot access ATA Manager: %d\n", (int) status);
  310.         exit(EXIT_FAILURE);
  311.     }
  312.  
  313. // Disable the CD driver 
  314.     status = OpenDriver("\p.AppleCD", &drvrRefNum);    
  315.     if (status == noErr) {
  316.         printf("Found .AppleCD driver, preparing to disable it\n");
  317.         status = DisableCDDriver(drvrRefNum);
  318.      }
  319.     
  320. // Display ATA Device Info
  321.     status = ScanATABusses();
  322.     if (status != noErr) {
  323.         printf("Cannot access ATA Manager: %d\n", (int) status);
  324.         exit(EXIT_FAILURE);
  325.     }
  326.     
  327. // Renable the CD driver
  328.     if(drvrRefNum != 0)
  329.     {
  330.         printf("Re-enabling the .AppleCD driver \n");
  331.         status = EnableCDDriver(drvrRefNum);
  332.     }
  333.     
  334.     
  335. }
  336.  
  337.  
  338. // ---------------------------------------------------------------------------
  339. OSErr         DisplayATAManagerInquiryInfo (void)
  340. // ---------------------------------------------------------------------------
  341. //
  342. //  Display information about the ATA Manager
  343. //
  344. {
  345.     ataMgrInquiry    pb;
  346.     OSErr            status;
  347.  
  348.     CLEAR(pb);
  349.     
  350.     pb.ataPBFunctionCode =    kATAMgrManagerInquiry;
  351.     pb.ataPBVers =            kATAPBVers1;
  352.  
  353.     status = ataManager((ataPB*) &pb );
  354.     IF_ERROR(status, "ATA Manager Inquiry failed\n")
  355.  
  356.     printf("ATA Manager inquiry:\n");
  357.     PrintNumVersion("\tATA Manager Version:", pb.ataMgrVersion);
  358.     printf("\tBusses:\t\t%d\n\tDevices:\t%d\n",
  359.                 pb.ataBusCnt, pb.ataDevCnt);
  360.     printf("\tPIO Modes:\t%x\n\tDMA Modes:\t%d\n\tMulti DMA Modes:%x\n",
  361.                  pb.ataPioModes, pb.ataSingleDMAModes, pb.ataMultiDMAModes);
  362.     printf("-----------------------------------------\n\n");    
  363.     return (status);
  364. }
  365.  
  366.  
  367. // ---------------------------------------------------------------------------
  368. OSErr         ScanATABusses (void)
  369. // ---------------------------------------------------------------------------
  370. //
  371. //  Display information about the ATA Busses
  372. //
  373. {
  374.     ataDrvrRegister        pb;
  375.     OSErr                status;
  376.  
  377. // Get first device ID (yes you have to do this once)
  378.     CLEAR(pb);
  379.     pb.ataPBFunctionCode     =    kATAMgrFindDriverRefnum;
  380.     pb.ataPBVers            =    kATAPBVers1;
  381.     pb.ataPBDeviceID         =     (UInt32)0x0000ffff;
  382.     status                     =     ataManager((ataPB*) &pb );
  383.  
  384. // loop through devices
  385.     for    (pb.ataPBDeviceID = (UInt32) pb.ataDeviceNextID;
  386.          pb.ataPBDeviceID != 0xff;
  387.          pb.ataPBDeviceID = (UInt32) pb.ataDeviceNextID)
  388.         {             
  389.             status = ataManager((ataPB*) &pb );
  390.             IF_ERROR(status, "ATA Find Driver failed\n")
  391.             
  392.             printf("\nDevice %d %#s\n", pb.ataPBDeviceID, DrvrRefToName(pb.ataDrvrRefNum) );
  393.             DisplayATADriveIdentity(pb.ataPBDeviceID);
  394.             
  395.         printf("-----------------------------------------\n");    
  396.         };    
  397.     
  398.     printf("\n");    
  399.     return (status);
  400. }
  401.  
  402.  
  403.  
  404. // ---------------------------------------------------------------------------
  405. OSErr         DisplayATADriveIdentity (UInt32 deviceID)
  406. // ---------------------------------------------------------------------------
  407. //
  408. //  Display information about the ATA Identify Info
  409. //
  410. {
  411.     ataIdentify            pb;
  412.     ataDevConfiguration    pb1;
  413.     
  414.     UInt16        buffer[256];
  415.     OSErr        status;
  416.     
  417.  
  418. // Get Driver Configuration
  419.     CLEAR(pb1);
  420.     pb1.ataPBFunctionCode     =    kATAMgrGetDrvConfiguration;
  421.     pb1.ataPBVers            =    kATAPBVers2;
  422.     pb1.ataPBDeviceID         =    deviceID;
  423.     
  424.     status = ataManager((ataPB*) &pb1 );
  425.     IF_ERROR(status, "ATA GetDrvConfiguration failed\n")
  426.  
  427.  
  428. // Setup Identify block;
  429.     CLEAR(pb);
  430.     pb.ataPBFunctionCode     =    kATAMgrDriveIdentify;
  431.     pb.ataPBVers            =    kATAPBVers1;
  432.     pb.ataPBDeviceID        =    deviceID;
  433.      pb.ataPBFlags             =     mATAFlagIORead + mATAFlagByteSwap ;
  434.      
  435.      if(pb1.ataDeviceType == kDevATAPI) pb.ataPBFlags += mATAFlagProtocol1;
  436.      
  437.     pb.ataPBTimeOut            =    100;
  438.     pb.ataPBBuffer            =    (void*) buffer;
  439.     
  440.     status = ataManager((ataPB*) &pb );
  441.     IF_ERROR(status, "ATA DriveIdentify failed\n")
  442.  
  443.     printf("Configuration: (");
  444.  
  445.     switch(pb1.ataDeviceType){
  446.         case kDevUnknown:    
  447.                         printf("Unknown protocol"); 
  448.                         break;
  449.         
  450.         case kDevATA:
  451.                         printf("ATA"); 
  452.                         break;
  453.                              
  454.         case kDevATAPI:    
  455.                         printf("ATAPI"); 
  456.                         break;
  457.                         
  458.         case kDevPCMCIA:    
  459.                         printf("PCMCIA"); 
  460.                         break;
  461.     }
  462.     
  463.     switch(pb1.ataSocketType){
  464.         case kSocketUnknown:    
  465.                         printf(", Unknown Socket"); 
  466.                         break;
  467.         
  468.         case kSocketInternal:
  469.                         printf(", Internal"); 
  470.                         break;
  471.                              
  472.         case kSocketMediaBay:    
  473.                         printf(", Media Bay"); 
  474.                         break;
  475.                         
  476.         case kkSocketPCMCIA:    
  477.                         printf(", PCMCIA, Vcc=%d, Vpp1=%d, Vpp2=%d", 
  478.                                         pb1.atapcVcc, pb1.atapcVpp1,pb1.atapcVpp2); 
  479.                         break;
  480.     }
  481.  
  482.     printf(")\n");
  483.  
  484.     DumpFormatedBuffer(buffer, kIdentFormat);
  485. };
  486.  
  487.  
  488.  
  489. // ---------------------------------------------------------------------------
  490. OSErr         DisableCDDriver (SInt16 refNum)
  491. // ---------------------------------------------------------------------------
  492. //
  493. // Disable the CD driver
  494. //
  495. {    OSErr status;
  496.     printf("- Disable the CD Driver \n");
  497.  
  498.      // wake up drive
  499.     status = WakeUpCDDrive (refNum);
  500.     if (status != noErr)
  501.     {
  502.         return status;
  503.     }
  504.  
  505.     // move driver to quiescent mode
  506.     status = SetQuiescence (refNum, quiescenceON);
  507.     if (status != noErr)
  508.     {
  509.         return status;
  510.     }
  511.  
  512.     return noErr;
  513. }
  514.  
  515. // ---------------------------------------------------------------------------
  516. OSErr         EnableCDDriver (SInt16 refNum)
  517. // ---------------------------------------------------------------------------
  518. //
  519. //  Re-enable the CD driver
  520. //
  521. {    OSErr status;
  522.  
  523.     printf("- Enable the CD Driver \n");
  524.  
  525.     // move driver to quiescent mode
  526.     status = SetQuiescence (refNum, quiescenceOFF);
  527.     if (status != noErr)
  528.     {
  529.         return status;
  530.     }
  531.  
  532.     return noErr;
  533. }
  534.  
  535. // ---------------------------------------------------------------------------
  536. OSErr         WakeUpCDDrive (SInt16 refNum)
  537. // ---------------------------------------------------------------------------
  538. //
  539. //  Re-enable the CD driver
  540. //
  541. {    CntrlParam    pb;
  542.     OSErr        status;
  543.  
  544.     printf("-- Wake up the CD Driver \n");
  545.  
  546.     CLEAR(pb);
  547.  
  548.      pb.ioCRefNum = refNum;
  549.     pb.csCode = csSetPowerMode;
  550.     *(UInt8 *) &pb.csParam[0] = pmActive;
  551.     
  552.   // send command to the CD/DVD driver
  553.     status = PBControlImmed ((ParmBlkPtr) &pb);
  554.  
  555.      return status;
  556. }
  557.  
  558. // ---------------------------------------------------------------------------
  559. OSErr         SetQuiescence (SInt16 refNum, UInt16 mode)
  560. // ---------------------------------------------------------------------------
  561. //
  562. //  Re-enable the CD driver
  563. //
  564. {
  565.     CntrlParam    pb;
  566.     OSErr        status;
  567.  
  568.     printf("-- Set the CD Driver Quiescence mode to %s\n",  
  569.         (mode ==quiescenceOFF)? "Off":"On");
  570.  
  571.     CLEAR(pb);
  572.  
  573.      pb.ioCRefNum = refNum;
  574.     pb.csCode = csQuiescence;
  575.     pb.csParam[0] = mode;
  576.     
  577.   // send command to the CD/DVD driver
  578.     status = PBControlImmed ((ParmBlkPtr) &pb);
  579.  
  580.      return status;
  581. }
  582.  
  583.  
  584. // ---------------------------------------------------------------------------
  585. Boolean     ATAManagerPresent    (void)
  586. // ---------------------------------------------------------------------------
  587. //
  588. // returns true if this machine has the ata manager
  589. //
  590. {
  591.         return (TrapAvailable(kATATrap));
  592. }
  593.  
  594. // ---------------------------------------------------------------------------
  595. Boolean     ATAHardwarePresent        (void)
  596. // ---------------------------------------------------------------------------
  597. //
  598. // returns true if this machine has ata hardware
  599. //
  600. {
  601.     UInt16    configFlags;
  602.  
  603.     // Hardware configuration flags
  604.     configFlags = LMGetHWCfgFlags();
  605.     
  606.     return (configFlags & 0x0080);
  607. }
  608.  
  609. //------------------------------------------------------------------------------------
  610. #pragma mark -
  611.  
  612. #define NumToolboxTraps() (                                \
  613.         (NGetTrapAddress(_InitGraf, ToolTrap)            \
  614.                 == NGetTrapAddress(0xAA6E, ToolTrap))    \
  615.             ? 0x200 : 0x400                                \
  616.     )
  617. #define GetTrapType(theTrap) (                            \
  618.         (((theTrap) & 0x800) != 0) ? ToolTrap : OSTrap    \
  619.     )
  620.  
  621. // ---------------------------------------------------------------------------
  622. Boolean     TrapAvailable        (short theTrap)
  623. // ---------------------------------------------------------------------------
  624. // (see Inside Mac VI 3-8)
  625. {
  626.         TrapType                trapType;
  627.         
  628.         trapType = GetTrapType(theTrap);
  629.         if (trapType == ToolTrap) {
  630.             theTrap &= 0x07FF;
  631.             if (theTrap >= NumToolboxTraps())
  632.                 theTrap = _Unimplemented;
  633.         }
  634.         return (
  635.             NGetTrapAddress(theTrap, trapType)
  636.             != NGetTrapAddress(_Unimplemented, ToolTrap)
  637.         );
  638. }
  639.  
  640. // ---------------------------------------------------------------------------
  641. void         PrintNumVersion        (char *label, NumVersion version )
  642. // ---------------------------------------------------------------------------
  643. //
  644. //    Decode version number info
  645. //
  646. {
  647.     char            *stage;
  648.  
  649.     switch (version.stage) {
  650.     case developStage:    stage = "d";        break;
  651.     case alphaStage:    stage = "a";        break;
  652.     case betaStage:        stage = "b";        break;
  653.     case finalStage:    stage = "";            break;
  654.     default:            stage = "?";        break;
  655.     
  656.     }
  657.     printf("%s %d.%d.%d",
  658.         label,
  659.         version.majorRev,
  660.         (version.minorAndBugRev>>4), (version.minorAndBugRev & 0xf),
  661.         stage);
  662.     if(version.stage != finalStage) printf(".%d",version.nonRelRev);
  663.     
  664.     printf(" (hex %08lx)\n",    (* ((unsigned long *) &version)));
  665. }
  666.  
  667.  
  668.  
  669. // ---------------------------------------------------------------------------
  670. void        DumpFormatedBuffer    (void* p,  const FormatTablePtr format) 
  671. // ---------------------------------------------------------------------------
  672. //
  673. // Dump formatted buffer
  674. //
  675.  
  676. {    
  677.     unsigned short            *idInfo = p;
  678.          
  679.     register char            *charField;
  680.     register short            fieldLength;
  681.     register short            i;
  682.     register long            value;
  683.     register FormatTablePtr    formatPtr;
  684.     
  685. #define FORMAT    (*formatPtr)
  686.  
  687.     for (formatPtr = format; FORMAT.format != kEndOfTable; formatPtr++) {
  688.             printf("%35s", FORMAT.label);
  689.             switch (FORMAT.format) {
  690.             // Decimal values come as two words with the words swapped.
  691.             case kDecimal:
  692.                 value = 0;
  693.                 for (i = FORMAT.lastWord; i >= FORMAT.firstWord; i--) {
  694.                     value <<= 16;
  695.                     value += idInfo[i];
  696.                 }
  697.                 printf(" %lu", value);    // was %lu
  698.                 break;
  699.             case kHex:
  700.                 for (i = FORMAT.lastWord; i >= FORMAT.firstWord; i--) {
  701.                     value = idInfo[i];
  702.                     printf(" %04ld", value);
  703.                 }
  704.                 break;
  705.             case kLeftJust:
  706.                 charField = (char *) &idInfo[FORMAT.firstWord];
  707.                 fieldLength = (FORMAT.lastWord - FORMAT.firstWord + 1)
  708.                             * sizeof (unsigned short);
  709.                 /*
  710.                  * First scan for an unspecified field.
  711.                  */
  712.                 for (i = 0; i <= fieldLength; i++) {
  713.                     if (charField[i] != '\0')
  714.                         goto gotLeftJustField;
  715.                 }
  716.                 printf(" <not specified>");
  717.                 break;
  718. gotLeftJustField:
  719.                 for (i = fieldLength; i > 0; --i) {
  720.                     if (charField[i - 1] != ' ')
  721.                         break;
  722.                 }
  723.                 printf(" \"%.*s\"", (int) i, charField);
  724.                 break;
  725.             case kRightJust:
  726.                 charField = (char *) &idInfo[FORMAT.firstWord];
  727.                 fieldLength = (FORMAT.lastWord - FORMAT.firstWord + 1)
  728.                             * sizeof (unsigned short);
  729.                 /*
  730.                  * First scan for an unspecified field.
  731.                  */
  732.                 for (i = 0; i <= fieldLength; i++) {
  733.                     if (charField[i] != '\0')
  734.                         goto gotRightJustField;
  735.                 }
  736.                 printf(" <not specified>");
  737.                 break;
  738. gotRightJustField:
  739.                 for (i = 0; i < fieldLength; i++) {
  740.                     if (charField[i] != ' ')
  741.                         break;
  742.                 }
  743.                 printf(" \"%.*s\"", (int) (fieldLength - i), &charField[i]);
  744.                 break;
  745.             }
  746.             printf("\n");
  747.         }
  748. //        DumpRawBuffer( p,512);
  749. }    
  750.     
  751. // ---------------------------------------------------------------------------
  752. void        DumpRawBuffer        ( UInt8 *bufferPtr, int length )
  753. // ---------------------------------------------------------------------------
  754. //
  755. // Dump buffer
  756. //
  757.  
  758. {
  759.         register int            i;
  760.         int                        lineStart;
  761.         int                        lineLength;
  762.         short                    c;
  763.  
  764. #define kLineSize    16
  765.         for (lineStart = 0; lineStart < length; lineStart += lineLength) {
  766.             lineLength = kLineSize;
  767.             if (lineStart + lineLength > length)
  768.                 lineLength = length - lineStart;
  769.             printf("%03x %3d:", lineStart, lineStart);
  770.             for (i = 0; i < lineLength; i++)
  771.                 printf(" %02x", bufferPtr[lineStart + i] & 0xFF);
  772.             for (; i < kLineSize; i++)
  773.                 printf("   ");
  774.             printf("  ");
  775.             for (i = 0; i < lineLength; i++) {
  776.                 c = bufferPtr[lineStart + i] & 0xFF;
  777.                 if (c > ' ' && c < '~')
  778.                     printf("%c", c);
  779.                 else {
  780.                     printf(".");
  781.                 }
  782.             }
  783.             printf("\n");
  784.         }
  785. }
  786.  
  787.  
  788.         
  789. // ---------------------------------------------------------------------------
  790. char*        DrvrRefToName(short refNum)
  791. // ---------------------------------------------------------------------------
  792. //
  793. //  lookup driver name in table
  794. //
  795.  
  796. {
  797.         AuxDCEHandle*        UTable  = (AuxDCEHandle*) LMGetUTableBase();
  798.         DCtlPtr                dctl;
  799.         Ptr                    p;    
  800.         
  801.         if(!refNum) return ((char*) "\p<none>");
  802.  
  803.         dctl = (DCtlPtr) *UTable[~refNum];
  804.         p      =  dctl->dCtlDriver;
  805.         if( dctl->dCtlFlags  & 0x0040) p = (void*) *p;
  806.  
  807.         return  ( p?(char*) (p+18):(char*)"\p-Purged-");
  808. }
  809.